package org.hs.phd.odi.tracking.tool.annotation;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.prefs.Preferences;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.hs.phd.common.simpleplayer.FramViewerController;
import org.hs.phd.common.simpleplayer.FramePlayer;
import org.hs.phd.common.simpleplayer.PlayerEvent;
import org.hs.phd.common.simpleplayer.PlayerEvent.EventType;
import org.hs.phd.common.simpleplayer.PlayerListener;
import org.hs.phd.common.simpleplayer.overlay.PolygonalOverlay;
import org.hs.phd.odi.tracking.filters.TrackSelectionEvent;
import org.hs.phd.odi.tracking.performanceevaluation.GroundTruthBroadcastEvent;
import org.hs.phd.odi.tracking.tracker.TrackInfo;

public class TrackAnnotationFrame extends JFrame implements PlayerListener {

	private static final String PREF_LAST_DIR = "PREF_LAST_DIR";
	private Component frameViewer;
	private final FramePlayer player;
	private FramViewerController viewerController;

	private TrackInfo trackinfo;
	
	private JFileChooser fileChooser;
	private JTextField selectedFileTextField;
	private JButton loadButton;
	private JButton saveButton;
	private JButton newButton;
	
	private File currentFile;
	

	public TrackAnnotationFrame(FramePlayer player) {
		super("Track Annotation Tool");
		this.player = player;
		trackinfo = new TrackInfo();
		player.addEventListener(this);
		this.frameViewer = player.getViewerComponent();
		this.viewerController = player.getViewerController();
		createFileChooser();
		contructGUI();
	}

	private void createFileChooser() {
		fileChooser =  new JFileChooser();
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		String lastDir = getPreference(PREF_LAST_DIR, null);
		
		if(lastDir != null){
			fileChooser.setCurrentDirectory( new File(lastDir) );
		}
	}
	
	private String getPreference(String name, String defaultValue){
		return Preferences.userNodeForPackage(getClass()).get(name, defaultValue);
	}

	private void setPreference(String name, String value){
		Preferences.userNodeForPackage(getClass()).put(name, value);
	}

	private void loadAnnotationsFromCurrentFile(){
		try {
			trackinfo.load(new FileInputStream(currentFile));
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
		repaint();
	}

	private void saveAnnotationsToCurrentFile(){
		try {
			trackinfo.save(new FileOutputStream(currentFile));
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

	private void contructGUI() {
		JPanel pnlButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlButtons.setBorder(BorderFactory.createEtchedBorder());

		selectedFileTextField = new JTextField(30);
		selectedFileTextField.setEditable(false);
		loadButton = new JButton("Load");
		saveButton = new JButton("Save");
		newButton = new JButton("New");

		pnlButtons.add(selectedFileTextField);
		pnlButtons.add(loadButton);
		pnlButtons.add(saveButton);
		pnlButtons.add(newButton);

		viewerController.setScale(0.75f);
		// frameViewer.setScale(1);

		JPanel pnlViewer = new JPanel(new BorderLayout());
		pnlViewer.setBorder(BorderFactory.createEtchedBorder());
		pnlViewer.add(frameViewer, BorderLayout.CENTER);

		getContentPane().add(pnlButtons, BorderLayout.NORTH);
		getContentPane().add(pnlViewer, BorderLayout.CENTER);
		
		loadButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				int result = fileChooser.showOpenDialog(TrackAnnotationFrame.this);
				
				if(result == JFileChooser.APPROVE_OPTION){
					currentFile = fileChooser.getSelectedFile();
					selectedFileTextField.setText(currentFile.getAbsolutePath());
					setPreference(PREF_LAST_DIR, fileChooser.getCurrentDirectory().getAbsolutePath());
				}
				
				if(currentFile != null){
					loadAnnotationsFromCurrentFile();
				}
			}
		});

		saveButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				if (currentFile == null) {

					int result = fileChooser.showSaveDialog(TrackAnnotationFrame.this);

					if (result == JFileChooser.APPROVE_OPTION) {
						currentFile = fileChooser.getSelectedFile();
						selectedFileTextField.setText(currentFile.getAbsolutePath());
						setPreference(PREF_LAST_DIR, fileChooser.getCurrentDirectory().getAbsolutePath());
					}
				}

				if (currentFile != null) {
					saveAnnotationsToCurrentFile();
				}
			}
		});

		newButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				int result = fileChooser.showSaveDialog(TrackAnnotationFrame.this);

				if (result == JFileChooser.APPROVE_OPTION) {
					currentFile = fileChooser.getSelectedFile();
					selectedFileTextField.setText(currentFile.getAbsolutePath());
					setPreference(PREF_LAST_DIR, fileChooser.getCurrentDirectory().getAbsolutePath());
				}
			}
		});

	}

	@Override
	public void playerEventOccurred(PlayerEvent event) {
		if (event instanceof TrackSelectionEvent) {

			TrackSelectionEvent selectionEvent = (TrackSelectionEvent) event;

			PolygonalOverlay overlay = createPolygonalOverlay(selectionEvent.getSelectionShape());
			event.getPlayer().getCurrentFrame().addOverlay(this, 0, overlay);
			event.getPlayer().refreshViewer();
			
			long frameNo = event.getPlayer().getCurrentFrame().getFrameNo();
			trackinfo.setInfo(frameNo, selectionEvent.getSelectionShape());
			event.getPlayer().fireEvent(new GroundTruthBroadcastEvent(frameNo,trackinfo.getInfo(frameNo)));
			
		} else if (event.getEventType() == EventType.STEP_NEXT || event.getEventType() == EventType.STEP_PREVIOUS) {
			long frameNo = event.getPlayer().getCurrentFrame().getFrameNo();
			if( trackinfo.isInfoAvailable(frameNo) ){
				event.getPlayer().getCurrentFrame().addOverlay(this, 0, createPolygonalOverlay(trackinfo.getInfo(frameNo)));
				event.getPlayer().refreshViewer();
				event.getPlayer().fireEvent(new GroundTruthBroadcastEvent(frameNo,trackinfo.getInfo(frameNo)));
			}
		}
	}

	private PolygonalOverlay createPolygonalOverlay(Polygon polygon) {
		return new PolygonalOverlay(polygon, Color.CYAN, new BasicStroke(2));
	}

}
